package com.yyzw.activiti.modeler.service.impl;

import com.yyzw.activiti.modeler.service.EndTaskService;
import javafx.geometry.Orientation;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.pvm.process.ProcessDefinitionImpl;
import org.activiti.engine.impl.pvm.process.TransitionImpl;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class EndTaskServiceImpl implements EndTaskService {
    @Autowired
    RepositoryService repositoryService;

    @Autowired
    TaskService taskService;

    @Autowired
    RuntimeService runtimeService;

    @Override
    public ActivityImpl findActivitiImpl(String taskId, String end) throws Exception{
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity)
                ((RepositoryServiceImpl) repositoryService).getDeployedProcessDefinition(task.getProcessDefinitionId());
        if(processDefinition==null){
            throw  new Exception("未找到定义流程信息！");
        }
        //获取当前活动节点ID
        if(StringUtils.isBlank(end)){
            end = task.getTaskDefinitionKey();
        }
        //根据流程定义，获取该流程实例的结束节点
        if(end.toLowerCase().equals("end")){
            for (ActivityImpl activitiImpl: processDefinition.getActivities()) {
                List<PvmTransition> pvmTransitionList = activitiImpl.getOutgoingTransitions();
                if(pvmTransitionList.isEmpty()){
                    return activitiImpl;
                }

            }
        }
        ActivityImpl activitiImpl = ((ProcessDefinitionImpl) processDefinition).findActivity(end);
        return activitiImpl;
    }

    @Override
    public void commitProcess(String taskId, Map<String,Object> variables, String activityId) throws Exception{
        if(variables==null){
            variables = new HashMap<>();
        }
        //跳转节点为空，默认提交操作
        if(StringUtils.isBlank(activityId)){
            taskService.complete(taskId,variables);
        }else{
            //流程转向操作
            //当前节点
            ActivityImpl currActivity = findActivitiImpl(taskId, null);
            //清空当前流向
            List<PvmTransition> oriPvmTransitionList = clearTransition(currActivity);
            //创建新的流向
            TransitionImpl newTransition = currActivity.createOutgoingTransition();
            //目标节点
            ActivityImpl pointActivity = findActivitiImpl(taskId, activityId);
            //设置新流向的目标节点
            newTransition.setDestination(pointActivity);
            //执行转向任务
            taskService.complete(taskId,variables);
            //删除目标节点新流入
            pointActivity.getIncomingTransitions().remove(newTransition);
            //还原以前流向
            restoreTransition(currActivity,oriPvmTransitionList);
        }

    }

    private void restoreTransition(ActivityImpl currActivity, List<PvmTransition> oriPvmTransitionList) {
      //清空现有流向
        List<PvmTransition> pvmTransitionList = currActivity.getOutgoingTransitions();
        pvmTransitionList.clear();
        //还原以前流程
        for (PvmTransition pvmTransition : oriPvmTransitionList) {
            pvmTransitionList.add(pvmTransition);

        }
    }

    private List<PvmTransition> clearTransition(ActivityImpl currActivity) {
        //存储当前节点所有流向临时变量
        List<PvmTransition> oriPvmTransitionList =new ArrayList<PvmTransition>();
        //获取当前节点所有流向，存储到临时变量，然后清空
        List<PvmTransition> pvmTransitionList = currActivity.getOutgoingTransitions();
        for (PvmTransition pvmTransition: pvmTransitionList) {
            oriPvmTransitionList.add(pvmTransition);
        }
        pvmTransitionList.clear();
        return oriPvmTransitionList;
    }

    /***
     * 流程回退
     * @param taskId 当前节点ID
     * @param activityId 退回节点ID
     * @param variables 流程存储参数信息
     * @throws Exception
     */
    @Override
    public void backProcess(String taskId,String activityId,Map<String,Object> variables) throws Exception{
      if(StringUtils.isEmpty(activityId)){
          throw  new Exception("回退节点ID为空！");
      }
      //查找所有并行的节点任务同时接受驳回
        List<Task> taskList = findTaskListByKey(findProcessInstanceByTaskId(taskId).getId(),findTaskById(taskId).getTaskDefinitionKey());
        for (Task task: taskList) {
            commitProcess(task.getId(),null,activityId);
        }
    }

    /***
     * 查询所有任务的并行节点
     * @param id
     * @param taskDefinitionKey
     * @return
     */
    private List<Task> findTaskListByKey(String id, String taskDefinitionKey) {
       return taskService.createTaskQuery().processInstanceId(id).taskDefinitionKey(taskDefinitionKey).list();
    }

    /***
     * 根据任务ID获取对应的流程实例信息
     * @param taskId 任务ID
     * @return
     */
    private ProcessInstance findProcessInstanceByTaskId(String taskId) throws Exception {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().
                processInstanceId(findTaskById(taskId).getProcessInstanceId()).singleResult();
        if(processInstance==null){
            throw new Exception("未找到流程实例");
        }
        return processInstance;
    }

    private Task findTaskById(String taskId) throws Exception{
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if(task==null){
            throw new Exception("未找到任务");
        }
        return task;
    }



}
